package com.copa.ums.modules.ums.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.copa.ums.common.api.CommonPage;
import com.copa.ums.common.vo.ResponseVo;
import com.copa.ums.modules.ums.model.UmsMenu;
import com.copa.ums.modules.ums.mapper.UmsMenuMapper;
import com.copa.ums.modules.ums.service.UmsMenuService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.copa.ums.modules.ums.vo.UmsMenuNodeVo;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author copa
 * @since 2022-10-31
 */
@Service
public class UmsMenuServiceImpl extends ServiceImpl<UmsMenuMapper, UmsMenu> implements UmsMenuService {

    @Resource
    private UmsMenuMapper menuMapper;

    @Override
    public List<UmsMenu> getMenuList(Long userId) {
        return menuMapper.getMenuList(userId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseVo<String> create(UmsMenu menu) {
        //menu.setCreateTime(new Date());
        menu.setId(null);
        updateLevel(menu);
        return save(menu)
                ? ResponseVo.success(null)
                : ResponseVo.failed();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseVo<String> update(Long menuId, UmsMenu menu) {
        menu.setId(menuId);
        updateLevel(menu);
        return updateById(menu)
                ? ResponseVo.success(null)
                : ResponseVo.failed();
    }

    @Override
    public ResponseVo<CommonPage<UmsMenu>> list(Long parentId, Integer pageSize, Integer pageNum) {
        Page<UmsMenu> page = new Page<>(pageNum, pageSize);
        QueryWrapper<UmsMenu> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(UmsMenu::getParentId, parentId)
                .orderByDesc(UmsMenu::getSort);
        return ResponseVo.success(CommonPage.restPage(page(page, wrapper)));
    }

    @Override
    public ResponseVo<List<UmsMenuNodeVo>> treeList() {
        List<UmsMenu> menuList = list();
        List<UmsMenuNodeVo> result = menuList.stream()
                .filter(menu -> menu.getParentId().equals(0L))
                .map(menu -> covertMenuNode(menu, menuList)).collect(Collectors.toList());
        return ResponseVo.success(result);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseVo<String> updateHidden(Long menuId, Integer hidden) {
        UmsMenu umsMenu = new UmsMenu();
        umsMenu.setId(menuId);
        umsMenu.setHidden(hidden);
        return updateById(umsMenu)
                ? ResponseVo.success(null)
                : ResponseVo.failed();
    }

    @Override
    public List<UmsMenu> listMenuByRoleId(Long roleId) {
        return menuMapper.listMenuByRoleId(roleId);
    }

    /**
     * 将UmsMenu转化为UmsMenuNodeVo并设置children属性
     */
    private UmsMenuNodeVo covertMenuNode(UmsMenu menu, List<UmsMenu> menuList) {
        UmsMenuNodeVo node = new UmsMenuNodeVo();
        BeanUtils.copyProperties(menu, node);
        List<UmsMenuNodeVo> children = menuList.stream()
                .filter(subMenu -> subMenu.getParentId().equals(menu.getId()))
                .map(subMenu -> covertMenuNode(subMenu, menuList)).collect(Collectors.toList());
        node.setChildren(children);
        return node;
    }

    /**
     * 修改菜单层级
     */
    private void updateLevel(UmsMenu menu) {
        if (menu.getParentId() == 0) {
            // 没有父菜单时为一级菜单
            menu.setLevel(0);
        } else {
            // 有父菜单时选择根据父菜单level设置
            UmsMenu parentMenu = getById(menu.getParentId());
            if (parentMenu != null) {
                menu.setLevel(parentMenu.getLevel() + 1);
            } else {
                menu.setLevel(0);
            }
        }
    }
}
